" Copyright 2011 The Go Authors. All rights reserved.
" Use of this source code is governed by a BSD-style
" license that can be found in the LICENSE file.
"
" indent/go.vim: Vim indent file for Go.
"
" TODO:
" - function invocations split across lines
" - general line splits (line ends in an operator)

if exists("b:did_indent")
	finish
endif
let b:did_indent = 1

" C indentation is too far off useful, mainly due to Go's := operator.
" Let's just define our own.
setlocal nolisp
setlocal autoindent
setlocal indentexpr=GoIndent(v:lnum)
setlocal indentkeys+=<:>,0=},0=)

if exists("*GoIndent")
	finish
endif

" use shiftwidth function only if it's available
if exists('*shiftwidth')
	func s:sw()
		return shiftwidth()
	endfunc
else
	func s:sw()
		return &sw
	endfunc
endif

function! GoIndent(lnum)
	let prevlnum = prevnonblank(a:lnum-1)
	if prevlnum == 0
		" top of file
		return 0
	endif

	" grab the previous and current line, stripping comments.
	let prevl = substitute(getline(prevlnum), '//.*$', '', '')
	let thisl = substitute(getline(a:lnum), '//.*$', '', '')
	let previ = indent(prevlnum)

	let ind = previ

	if prevl =~ '[({]\s*$'
		" previous line opened a block
		let ind += s:sw()
	endif
	if prevl =~# '^\s*\(case .*\|default\):$'
		" previous line is part of a switch statement
		let ind += s:sw()
	endif
	" TODO: handle if the previous line is a label.

	if thisl =~ '^\s*[)}]'
		" this line closed a block
		let ind -= s:sw()
	endif

	" Colons are tricky.
	" We want to outdent if it's part of a switch ("case foo:" or "default:").
	" We ignore trying to deal with jump labels because (a) they're rare, and
	" (b) they're hard to disambiguate from a composite literal key.
	if thisl =~# '^\s*\(case .*\|default\):$'
		let ind -= s:sw()
	endif

	return ind
endfunction

" vim:ts=4:sw=4:et
